import type { CSSProperties } from "react";
import Iconify from "@purge-icons/generated";
import SvgIcon from "./SvgIcon";
import { isString } from "@/utils/is";
import { useEffect, useMemo, useRef } from "react";
import { nextTick } from "@/utils";
import { pick } from "lodash-es";
import "../style/Icon.less";

interface PropType {
	// icon name
	icon: string;
	// icon color
	color?: string;
	// icon size
	size?: number;
	spin?: boolean;
	prefix?: string;
	onClick?: Fn;
}

const SVG_END_WITH_FLAG = "|svg";

const Icon = (props: PropType) => {
	// fix React18 "defaultProps" problem
	props = Object.assign({}, { size: 16, spin: false, prefix: "", ...props });

	const attrs = pick(props, ["className", "style"]) as Recordable<{ className: string; style: Object }>;
	const elRef = useRef<ElRef>(null);

	const isSvgIcon = useMemo(() => props.icon?.endsWith(SVG_END_WITH_FLAG), [props.icon]);
	const getSvgIcon = useMemo(() => props.icon.replace(SVG_END_WITH_FLAG, ""), [props.icon]);
	const getIconRef = useMemo(() => `${props.prefix ? `${props.prefix}:` : ""}${props.icon}`, [props.icon, props.prefix]);

	async function update() {
		if (isSvgIcon) return;

		const el = elRef.current;
		if (!el) return;

		await nextTick();
		const icon = getIconRef;
		if (!icon) return;
		const svg = Iconify.renderSVG(icon, {});
		if (svg) {
			el.textContent = "";
			el.appendChild(svg);
		} else {
			const span = document.createElement("span");
			span.className = "iconify";
			span.dataset.icon = icon;
			el.textContent = "";
			el.appendChild(span);
		}
	}

	const getAttrsClass = useMemo(() => {
		let classList = ["anticon app-iconify", attrs.className];
		if (props.spin) classList.push("app-iconify-spin");
		return classList.join(" ");
	}, [props.spin, attrs]);

	const getWrapStyle = useMemo((): CSSProperties => {
		const { size, color } = props;
		let fs = size;
		if (isString(size)) fs = Number.parseInt(size, 10);

		return {
			fontSize: `${fs}px`,
			color,
			display: "inline-flex"
		};
	}, [props.size, props.color]);

	useEffect(() => {
		update();
	}, [props.icon]);
	return isSvgIcon ? (
		<SvgIcon
			size={props.size}
			name={getSvgIcon}
			className={`anticon ${attrs.className}`}
			spin={props.spin}
			onClick={props.onClick}
		/>
	) : (
		<span ref={elRef} className={getAttrsClass} style={getWrapStyle} onClick={props.onClick} />
	);
};

export default Icon;
